import os
from .. import utils
from .. import config


def all_files(root, wanted_dirs_list, hated_dirs_list):
    """
    遍历指定目录并生成源文件，
    同时考虑 wanted 和 hated 目录列表。
    """
    scan_paths = []
    if wanted_dirs_list:
        # 如果指定了 wanted_dirs，则只扫描它们。
        for wanted in wanted_dirs_list:
            path = os.path.join(root, wanted)
            if os.path.isdir(path):
                scan_paths.append(path)
    else:
        # 否则，扫描整个根目录。
        scan_paths.append(root)

    for scan_path in scan_paths:
        for cwd, dirs, files in os.walk(scan_path, topdown=True):
            # 从遍历中排除 hated 目录
            dirs[:] = [d for d in dirs if d not in hated_dirs_list]
            for file in files:
                yield (
                    file,
                    os.path.join(cwd, file).replace("\\", "/"),
                    cwd.replace("\\", "/"),
                )


def scan_files(root, wanted_dirs_list, hated_dirs_list):
    """扫描所有文件，返回头文件目录和源文件列表"""
    header_dirs = list()
    source_files = list()
    for file, filepath, cwd in all_files(root, wanted_dirs_list, hated_dirs_list):
        if utils.is_header_file(file) and cwd not in header_dirs:
            header_dirs.append(cwd)
        elif utils.is_source_file(file):
            source_files.append(filepath)
    return header_dirs, source_files


def cook_header_dirs(root, header_dirs):
    """
    将头文件位置的父目录添加到包含路径中，
    直到定义的层级，以帮助在非标准布局中找到头文件。
    """
    additional_dirs = set()
    # 使用 header_dirs 的副本进行迭代，因为我们可能会修改原始集合
    for dir_path in set(header_dirs):
        current = dir_path
        for _ in range(config.header_dir_backtrace_level):
            parent = os.path.dirname(current)
            # 如果超出项目根目录或到达根目录本身，则停止
            if not parent or not parent.startswith(root) or parent == root:
                break
            additional_dirs.add(parent)
            current = parent
    # 将新目录添加到原始列表中，不带重复项
    header_dirs.extend(list(additional_dirs - set(header_dirs)))
